using System;
using NUnit.Framework;
using ValidationFramework.Reflection;

namespace ValidationFramework.Tests.Reflection
{

    public class PropertyDescriptorTest
    {
    	[TestFixture]
		public class Contructor
		{


			[Test]
			public void Instance()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "InstanceProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				Assert.AreEqual(propertyName, propertyDescriptor.Name);
				Assert.IsFalse(propertyDescriptor.IsStatic);
				Assert.AreEqual(1, propertyDescriptor.Rules.Count);
				Assert.AreEqual(propertyDescriptor, propertyDescriptor.Rules.InfoDescriptor);

				Assert.AreEqual(typeDescriptor.Properties.TypeDescriptor, typeDescriptor);
			}


			[Test]
			public void PrivateGet()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "PrivateGetProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				Assert.AreEqual(propertyName, propertyDescriptor.Name);
				Assert.IsFalse(propertyDescriptor.IsStatic);
				Assert.AreEqual(1, propertyDescriptor.Rules.Count);
				Assert.AreEqual(propertyDescriptor, propertyDescriptor.Rules.InfoDescriptor);

				Assert.AreEqual(typeDescriptor.Properties.TypeDescriptor, typeDescriptor);
			}


			[Test]
			public void PrivateSet()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "PrivateSetProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				Assert.AreEqual(propertyName, propertyDescriptor.Name);
				Assert.IsFalse(propertyDescriptor.IsStatic);
				Assert.AreEqual(1, propertyDescriptor.Rules.Count);
				Assert.AreEqual(propertyDescriptor, propertyDescriptor.Rules.InfoDescriptor);

				Assert.AreEqual(typeDescriptor.Properties.TypeDescriptor, typeDescriptor);
			}
			[Test]
			public void NoGet()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
                const string propertyName = "NoGetProperty";
			    foreach (var property in typeDescriptor.Properties)
			    {
                    Assert.AreNotEqual(propertyName, property.Name);
			    }
			}


			[Test]
			public void Static()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "StaticProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				Assert.AreEqual(propertyName, propertyDescriptor.Name);
				Assert.IsTrue(propertyDescriptor.IsStatic);
				Assert.AreEqual(1, propertyDescriptor.Rules.Count);
				Assert.AreEqual(propertyDescriptor, propertyDescriptor.Rules.InfoDescriptor);

				Assert.AreEqual(typeDescriptor.Properties.TypeDescriptor, typeDescriptor);

			}


			[Test]
			public void NoRules()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "PropertyWithNoRules";
				Assert.IsFalse(typeDescriptor.Properties.ContainsKey(propertyName));
			}


			[Test]
			public void InstanceWithNoRulesAndIncludeAttribute()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "PropertyWithNoRulesAndIncludeAttribute";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				Assert.AreEqual(propertyName, propertyDescriptor.Name);
				Assert.IsFalse(propertyDescriptor.IsStatic);
				Assert.AreEqual(0, propertyDescriptor.Rules.Count);
				Assert.AreEqual(propertyDescriptor, propertyDescriptor.Rules.InfoDescriptor);

				Assert.AreEqual(typeDescriptor.Properties.TypeDescriptor, typeDescriptor);
			}
		}


		[TestFixture]
		public class GetValue
		{


			[Test]
			public void Instance()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "InstanceProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				var descriptorsTest = new PropertyDescriptorTest {InstanceProperty = 10};
			    var value = propertyDescriptor.GetValue(descriptorsTest);

				Assert.AreEqual(10, value);
			}


			[Test]
			public void PrivateGet()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "PrivateGetProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				var descriptorsTest = new PropertyDescriptorTest {PrivateGetProperty = 10};
			    var value = propertyDescriptor.GetValue(descriptorsTest);
				Assert.AreEqual(10, value);
			}


			[Test]
			public void PrivateSet()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "PrivateSetProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];

				var descriptorsTest = new PropertyDescriptorTest {PrivateSetProperty = 10};
			    var value = propertyDescriptor.GetValue(descriptorsTest);

				Assert.AreEqual(10, value);
			}


			[Test]
			public void Static()
			{
				var runtimeTypeHandle = typeof(PropertyDescriptorTest).TypeHandle;
				var typeDescriptor = TypeCache.GetType(runtimeTypeHandle);
				const string propertyName = "StaticProperty";
				var propertyDescriptor = typeDescriptor.Properties[propertyName];
				StaticProperty = 10;
				var value = propertyDescriptor.GetValue(null);

				Assert.AreEqual(10, value);
			}

		}


        [RequiredIntRule]
        public int InstanceProperty
        {
            get;
            set;
        }
        [RequiredIntRule]
        public int NoGetProperty
        {
            set { throw new NotImplementedException(); }
        }


        public int PropertyWithNoRules
        {
        	get;
        	set;
        }

		[IncludeMember]
        public int PropertyWithNoRulesAndIncludeAttribute
        {
        	get;
        	set;
        }


    	[RequiredIntRule]
    	public int PrivateGetProperty
    	{
    		set;
    		private get;
    	}


    	[RequiredIntRule]
    	public int PrivateSetProperty
    	{
    		internal set;
    		get;
    	}


    	[RequiredIntRule]
        public static int StaticProperty
        {
        	get;
        	set;
        }


    }
}